package com.zwf.checkstyledemo1;

import com.puppycrawl.tools.checkstyle.*;
import com.puppycrawl.tools.checkstyle.api.*;
import com.puppycrawl.tools.checkstyle.checks.coding.*;
import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
import java.io.File;
import java.util.*;

public class CodeAnalyzer {

    public static void main(String[] args) throws Exception {
        String projectPath = "src/main/java";
        List<File> files = listJavaFiles(new File(projectPath));

        // 配置检查器
        List<AbstractCheck> checks = new ArrayList<>();
        checks.add(new CommentStatisticsCheck()); // 自定义统计检查器
        checks.add(new NullPointerCheck());       // 空指针检查
        checks.add(new DivisionByZeroCheck());    // 除零检查

        // 执行检查
        CheckResults results = runChecks(files, checks);

        // 输出结果
        System.out.println("代码总行数: " + results.totalLines);
        System.out.printf("注释率: %.2f%%\n", results.commentRate * 100);
        System.out.println("\n潜在空指针异常:");
        results.nullPointerViolations.forEach(System.out::println);
        System.out.println("\n潜在除零异常:");
        results.divisionByZeroViolations.forEach(System.out::println);
    }

    // 自定义结果容器
    static class CheckResults {
        int totalLines;
        double commentRate;
        List<String> nullPointerViolations = new ArrayList<>();
        List<String> divisionByZeroViolations = new ArrayList<>();
    }

    // 递归获取所有Java文件
    private static List<File> listJavaFiles(File dir) {
        List<File> javaFiles = new ArrayList<>();
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    javaFiles.addAll(listJavaFiles(file));
                } else if (file.getName().endsWith(".java")) {
                    javaFiles.add(file);
                }
            }
        }
        return javaFiles;
    }

    // 执行检查
    private static CheckResults runChecks(List<File> files, List<AbstractCheck> checks) throws Exception {
        CheckResults results = new CheckResults();
        Checker checker = new Checker();

        // 配置模块
        // 添加类加载器配置
        checker.setModuleClassLoader(Checker.class.getClassLoader());
        DefaultConfiguration config = createConfiguration(checks);
        checker.configure(config);

        // 添加监听器收集结果
        checker.addListener(new AuditListener() {
            private FileContents currentFileContents;

            @Override
            public void auditStarted(AuditEvent event) {}

            @Override
            public void auditFinished(AuditEvent event) {}

            @Override
            public void fileStarted(AuditEvent event) {}


            @Override
            public void fileFinished(AuditEvent event) {
                // 收集统计信息
                if (currentFileContents != null) {
                    String[] lines = currentFileContents.getLines();
                    results.totalLines = lines.length;

                    // 计算注释行数
                    int commentLines = currentFileContents.getSingleLineComments().size();
                    List<TextBlock> blockComments = (List<TextBlock>) currentFileContents.getBlockComments();
                    for (TextBlock block : blockComments) {
                        commentLines += (block.getEndLineNo() - block.getStartLineNo() + 1);
                    }

                    results.commentRate = results.totalLines > 0 ?
                            (double) commentLines / results.totalLines : 0.0;
                }
                currentFileContents = null;
            }

            @Override
            public void addError(AuditEvent event) {
                // 收集违规信息
                String msg = event.getFileName() + ":" + event.getLine() + " - " + event.getMessage();
                if ("null.pointer".equals(event.getSourceName())) {
                    results.nullPointerViolations.add(msg);
                } else if ("division.by.zero".equals(event.getSourceName())) {
                    results.divisionByZeroViolations.add(msg);
                }
            }

            @Override
            public void addException(AuditEvent event, Throwable throwable) {
                throwable.printStackTrace();
            }
        });

        // 处理所有文件
        for (File file : files) {
            checker.process(Collections.singletonList(file));
        }
        return results;
    }

    // 创建CheckStyle配置
    private static DefaultConfiguration createConfiguration(List<AbstractCheck> checks) {
        DefaultConfiguration config = new DefaultConfiguration("root");
        // 创建TreeWalker配置
        DefaultConfiguration treeWalker = new DefaultConfiguration("TreeWalker");
        config.addChild(treeWalker);
        for (AbstractCheck check : checks) {
            DefaultConfiguration checkConfig = new DefaultConfiguration(check.getClass().getName());
            treeWalker.addChild(checkConfig);
        }

        treeWalker.addAttribute("fileExtensions", "java");

        return config;
    }

    // 自定义统计检查器（行数/注释）
    public static class CommentStatisticsCheck extends AbstractCheck {
        @Override
        public int[] getDefaultTokens() {
            return CommonUtil.EMPTY_INT_ARRAY; // 不需要处理token
        }

        @Override
        public int[] getAcceptableTokens() {
            return new int[0];
        }

        @Override
        public int[] getRequiredTokens() {
            return new int[0];
        }

    }

    // 空指针检查器
    public static class NullPointerCheck extends AbstractCheck {
        @Override
        public int[] getDefaultTokens() {
            return new int[] { TokenTypes.METHOD_CALL };
        }

        @Override
        public int[] getAcceptableTokens() {
            return new int[0];
        }

        @Override
        public int[] getRequiredTokens() {
            return new int[0];
        }

        @Override
        public void visitToken(DetailAST ast) {
            DetailAST dot = ast.findFirstToken(TokenTypes.DOT);
            if (dot != null) {
                DetailAST child = dot.getFirstChild();
                if (child.getType() == TokenTypes.IDENT && "potentialNull".equals(child.getText())) {
                    log(ast.getLineNo(), "可能的空指针异常: " + child.getText());
                }
            }
        }

    }

    // 除零检查器
    public static class DivisionByZeroCheck extends AbstractCheck {
        @Override
        public int[] getDefaultTokens() {
            return new int[] { TokenTypes.DIV, TokenTypes.MOD };
        }

        @Override
        public int[] getAcceptableTokens() {
            return new int[0];
        }

        @Override
        public int[] getRequiredTokens() {
            return new int[0];
        }

        @Override
        public void visitToken(DetailAST ast) {
            DetailAST expr = ast.getFirstChild().getNextSibling();
            if (expr.getType() == TokenTypes.NUM_INT && "0".equals(expr.getText())) {
                log(ast.getLineNo(), "除零异常风险");
            }
        }
    }
}